﻿using System;
using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json;
using Teigha.Runtime;
using Teigha.DatabaseServices;
using Teigha.Geometry;
using Teigha.Colors;

namespace ConsoleApp
{
    public class GeoJsonConverter
    {
        // 坐标系转换参数（根据实际需求调整）
        private const double ScaleFactor = 1000; // 缩放比例 
        private const double OriginX = 0;       // 原点X偏移 
        private const double OriginY = 0;       // 原点Y偏移

        public void Convert(string geoJsonPath, string outputDwgPath)
        {
            // 初始化Teigha许可证
            //RuntimeServices.Initialize();
            HostApplicationServices.WorkingDatabase = null;

            // 加载GeoJSON 
            var geoJson = File.ReadAllText(geoJsonPath);
            var featureCollection = JsonConvert.DeserializeObject<GeoJsonFeatureCollection>(geoJson);

            // 创建CAD数据库 
            using (var db = new Database(true, true))
            using (var transaction = db.TransactionManager.StartTransaction())
            {
                // 获取模型空间块表
                var blockTable = (BlockTable)transaction.GetObject(db.BlockTableId, OpenMode.ForWrite);
                var modelSpace = (BlockTableRecord)transaction.GetObject(
                    blockTable[BlockTableRecord.ModelSpace], OpenMode.ForWrite);

                // 处理每个地理要素
                foreach (var feature in featureCollection.Features)
                {
                    string layerName = feature.Properties.TryGetValue("layer", out var layer)
                        ? layer.ToString() : "Default";

                    // 创建图层 
                    CreateLayer(db, transaction, layerName);

                    // 根据几何类型创建CAD实体
                    switch (feature.Geometry.Type)
                    {
                        case "Point":
                            CreateDbPoint(feature.Geometry, modelSpace, transaction, layerName);
                            break;
                        case "LineString":
                            CreatePolyline(feature.Geometry, modelSpace, transaction, layerName, false);
                            break;
                        case "Polygon":
                            CreatePolyline(feature.Geometry, modelSpace, transaction, layerName, true);
                            break;
                        case "MultiPolygon":
                            HandleMultiPolygon(feature.Geometry, modelSpace, transaction, layerName);
                            break;
                    }
                }

                // 保存DWG文件 
                db.SaveAs(outputDwgPath, DwgVersion.Current);
                transaction.Commit();
            }

            // 清理Teigha资源
            //RuntimeServices.Terminate();
        }

        private void CreateLayer(Database db, Transaction transaction, string layerName)
        {
            var layerTable = (LayerTable)transaction.GetObject(db.LayerTableId, OpenMode.ForRead);
            if (!layerTable.Has(layerName))
            {
                layerTable.UpgradeOpen();
                var layer = new LayerTableRecord
                {
                    Name = layerName,
                    Color = Color.FromColorIndex(ColorMethod.ByAci, 7) // 白色 
                };
                layerTable.Add(layer);
                transaction.AddNewlyCreatedDBObject(layer, true);
            }
        }

        private Point3d ConvertCoordinate(List<double> coordinate)
        {
            // WGS84经纬度转笛卡尔坐标（简化处理）
            double x = coordinate[0] * ScaleFactor - OriginX;
            double y = coordinate[1] * ScaleFactor - OriginY;
            return new Point3d(x, y, 0);
        }

        private void CreateDbPoint(GeoJsonGeometry geometry, BlockTableRecord modelSpace,
                                  Transaction transaction, string layerName)
        {
            var point = new DBPoint(ConvertCoordinate(geometry.Coordinates[0]));
            point.Layer = layerName;
            modelSpace.AppendEntity(point);
            transaction.AddNewlyCreatedDBObject(point, true);
        }

        private void CreatePolyline(GeoJsonGeometry geometry, BlockTableRecord modelSpace,
                                   Transaction transaction, string layerName, bool closePolygon)
        {
            foreach (var ring in geometry.Coordinates)
            {
                var polyline = new Polyline();
                polyline.Layer = layerName;

                for (int i = 0; i < ring.Count; i++)
                {
                    var point = ConvertCoordinate(ring[i]);
                    polyline.AddVertexAt(i, new Point2d(point.X, point.Y), 0, 0, 0);
                }

                if (closePolygon)
                {
                    polyline.Closed = true;
                }

                modelSpace.AppendEntity(polyline);
                transaction.AddNewlyCreatedDBObject(polyline, true);
            }
        }

        private void HandleMultiPolygon(GeoJsonGeometry geometry, BlockTableRecord modelSpace,
                                      Transaction transaction, string layerName)
        {
            foreach (var polygon in geometry.Coordinates)
            {
                foreach (var ring in polygon)
                {
                    var polyline = new Polyline();
                    polyline.Layer = layerName;

                    for (int i = 0; i < ring.Count; i++)
                    {
                        var point = ConvertCoordinate(ring[i]);
                        polyline.AddVertexAt(i, new Point2d(point.X, point.Y), 0, 0, 0);
                    }

                    polyline.Closed = true;
                    modelSpace.AppendEntity(polyline);
                    transaction.AddNewlyCreatedDBObject(polyline, true);
                }
            }
        }
    }

    #region GeoJSON 数据模型 
    public class GeoJsonFeatureCollection
    {
        [JsonProperty("features")]
        public List<GeoJsonFeature> Features { get; set; }
    }

    public class GeoJsonFeature
    {
        [JsonProperty("geometry")]
        public GeoJsonGeometry Geometry { get; set; }

        [JsonProperty("properties")]
        public Dictionary<string, object> Properties { get; set; }
    }

    public class GeoJsonGeometry
    {
        [JsonProperty("type")]
        public string Type { get; set; }

        // 坐标数据结构：
        // Point: List<double>
        // LineString: List<List<double>>
        // Polygon: List<List<List<double>>>
        // MultiPolygon: List<List<List<List<double>>>>
        [JsonProperty("coordinates")]
        public dynamic Coordinates { get; set; }
    }
    #endregion
}